package com.puzzlebazar.client.squaregrid.view;

import com.puzzlebazar.client.util.Recti;
import com.puzzlebazar.client.util.Vec2i;

/**
 * @author beaudoin
 *
 */
public final class DrawableUtils {


	/**
	 * Add a rectangle across edges in a square grid
	 * 
	 * @param loc1 Location of a corner cell
	 * @param loc2 Location of the diagonally opposed corner cell
	 * @param Layer Layer to add to
	 * @param style Name of the style to use for the FillDrawable
	 * @param name Name of the drawable to add
	 * @param size Size of the edges to draw
	 */
	static public void addEdgeRectangle( Vec2i loc1, Vec2i loc2, 
			DrawableLayer layer, 
			String style, String name, int size )
	{
		final Vec2i pt00 = Vec2i.getTopLeftVertex( loc1, loc2 );
		final Vec2i pt11 = Vec2i.getBottomRightVertex( loc1, loc2 );
		final Vec2i pt10 = new Vec2i( pt11.x, pt00.y );
		final Vec2i pt01 = new Vec2i( pt00.x, pt11.y );
		
		addEdgeRectangle(pt00, pt10, pt01, pt11, layer, style, name, size);		
	}
	
	
	/**
	 * Add a rectangle across edges in a square grid
	 * 
	 * @param rect  Rectangle of vertices to add
	 * @param Layer Layer to add to
	 * @param style Name of the style to use for the FillDrawable
	 * @param name Name of the drawable to add
	 * @param size Size of the edges to draw
	 */
	static public void addEdgeRectangle( Recti rect, DrawableLayer layer, 
			String style, String name, int size )
	{
		addEdgeRectangle(rect.getPt00(), 
				rect.getPt10(), 
				rect.getPt01(), 
				rect.getPt11(), layer, style, name, size);
	}


	/**
	 * Remove a rectangle drawn on edges
	 * 
	 * @param rect  Rectangle of vertices to remove
	 * @param Layer Layer to remove from
	 * @param name Name of the drawable to remove
	 */
	public static void removeEdgeRectangle(Recti rect,
			DrawableLayer layer, String name) {
		
		removeEdgeRectangle(rect.getPt00(), 
				rect.getPt10(), 
				rect.getPt01(), 
				rect.getPt11(), layer, name);		
		
	}


	/**
	 * Remove a rectangle drawn on edges in a square grid
	 * 
	 * @param loc1 Location of a corner cell
	 * @param loc2 Location of the diagonally opposed corner cell
	 * @param layer Layer to remove from
	 * @param name Name of the drawable to remove
	 */
	static public void removeEdgeRectangle( Vec2i loc1, Vec2i loc2, 
			DrawableLayer layer, 
			String name )
	{
		final Vec2i pt00 = Vec2i.getTopLeftVertex( loc1, loc2 );
		final Vec2i pt11 = Vec2i.getBottomRightVertex( loc1, loc2 );
		final Vec2i pt10 = new Vec2i( pt11.x, pt00.y );
		final Vec2i pt01 = new Vec2i( pt00.x, pt11.y );
		
		removeEdgeRectangle(pt00, pt10, pt01, pt11, layer, name );		
	}
	
	
	
	/**
	 * Adds an edge rectangle given 4 ordered vertex locations
	 * 
	 * @param pt00 Top-left vertex
	 * @param pt10 Top-right vertex
	 * @param pt01 Bottom-left vertex
	 * @param pt11 Bottom-right vertex
	 * @param layer Layer to remove from
	 * @param style Name of the style to use for the FillDrawable
	 * @param name Name of the drawable to remove
	 * @param size Size of the edges to draw
	 */
	private static void addEdgeRectangle(final Vec2i pt00, final Vec2i pt10,
			final Vec2i pt01, final Vec2i pt11,
			DrawableLayer layer, String style, String name, int size) {
		if( name == null ) name = new String("");
		
		try {
			addEdge( pt00, pt01, layer, style, name.concat("-left"), size, false );
			addEdge( pt00, pt10, layer, style, name.concat("-top"), size, false );
			addEdge( pt10, pt11, layer, style, name.concat("-right"), size, false );
			addEdge( pt01, pt11, layer, style, name.concat("-bottom"), size, false );
		}
		catch( Exception exception ) {
			exception.printStackTrace();
		}
	}

	/**
	 * Remove an edge rectangle given 4 ordered vertex locations
	 * 
	 * @param pt00 Top-left vertex
	 * @param pt10 Top-right vertex
	 * @param pt01 Bottom-left vertex
	 * @param pt11 Bottom-right vertex
	 * @param layer Layer to remove from
	 * @param name Name of the drawable to remove
	 */
	private static void removeEdgeRectangle(
			final Vec2i pt00, final Vec2i pt10,
			final Vec2i pt01, final Vec2i pt11,
			DrawableLayer layer, String name) {
		if( name == null ) name = new String("");
		
		try {
			removeEdge( pt00, pt01, layer, name.concat("-left") );
			removeEdge( pt00, pt10, layer, name.concat("-top") );
			removeEdge( pt10, pt11, layer, name.concat("-right") );
			removeEdge( pt01, pt11, layer, name.concat("-bottom") );
		}
		catch( Exception exception ) {
			exception.printStackTrace();
		}
	}	

	/**
	 * Remove the edge rectangle of a given name from a Layer. If
	 * multiple rectangles share the same name, they will all be deleted.
	 * 
	 * @param Layer Layer to remove from
	 * @param name Name of the drawable to remove
	 */
	public static void removeEdgeRectangle(DrawableLayer layer,
			String name) {
		
		layer.removeDrawable( name.concat("-left") );
		layer.removeDrawable( name.concat("-top") );
		layer.removeDrawable( name.concat("-right") );
		layer.removeDrawable( name.concat("-bottom") );
	}
	
	/**
	 * Add an edge to a drawable Layer
	 * 
	 * @param pt0 First point of the edge
	 * @param pt1 Second point of the edge (must lie horizontally or vertically)
	 * @param Layer Layer to add into
	 * @param style Name of the style to use for the FillDrawable
	 * @param name Name of the drawable to remove
	 * @param size Size of the edge to draw
	 * @param tight True to draw a "tight edge", perfectly aligned on the grid. False to extend the edge.
	 * @throws Exception
	 */
	public static void addEdge(Vec2i pt0, Vec2i pt1,
			DrawableLayer layer, String style,
			String name, int size, boolean tight) throws Exception {

		if( pt0.x != pt1.x && pt0.y != pt1.y ) 
			throw new Exception( "Invalid edge vertices" );
		
		int offset = size - (size/2);
		
		FillDrawable edge = new FillDrawable(name, style);
		Vec2i posOffset = new Vec2i(-offset,-offset);
		Vec2i sizeOffset = new Vec2i(size+1,size+1);		
		if( tight ) {
			if( pt0.x == pt1.x ) {
				posOffset.y = 0;
				sizeOffset.y = 0;
			}
			else {
				posOffset.x = 0;
				sizeOffset.x = 0;				
			}
		}
		edge.setPosOffset( posOffset );
		edge.setSizeOffset( sizeOffset );
		edge.setVertexRectangle( pt0, pt1 );
		layer.addDrawable( edge );
	}


	
	/**
	 * Remove an edge from a drawable Layer
	 * 
	 * @param pt0 First point of the edge
	 * @param pt1 Second point of the edge (must lie horizontally or vertically)
	 * @param layer Layer to add into
	 * @param name Name of the drawable to remove
	 * @throws Exception 
	 */
	public static void removeEdge(Vec2i pt0, Vec2i pt1,
			DrawableLayer layer,
			String name) throws Exception {

		if( pt0.x != pt1.x && pt0.y != pt1.y ) 
			throw new Exception( "Invalid edge vertices" );
		
		layer.removeVertexDrawable( pt0, pt1, name );
	}



	/**
	 * Add a vertex to a drawable Layer
	 * 
	 * @param pt Point of the vertex
	 * @param layer Layer to add into
	 * @param style Name of the style to use for the FillDrawable
	 * @param name Name of the drawable to remove
	 * @param size Size of the edge to draw
	 * @throws Exception
	 */
	public static void addVertex(Vec2i pt, 
			DrawableLayer layer, String style,
			String name, int size) throws Exception {		
		
		Drawable vertex = new FillDrawable(name,style);
		int offset = size - (size/2);
		vertex.setPosOffset( new Vec2i(-offset,-offset) );
		vertex.setSizeOffset( new Vec2i(size+1,size+1) );
		vertex.setVertex( pt );
		layer.addDrawable( vertex );
	}


	/**
	 * Removes a vertex from a drawable Layer
	 * 
	 * @param pt Point of the vertex
	 * @param layer Layer to add into
	 * @param name Name of the drawable to remove
	 * @throws Exception
	 */
	public static void removeVertex(Vec2i pt, 
			DrawableLayer layer, 
			String name) throws Exception {		
		layer.removeVertexDrawable( pt, name );
	}


}
